﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;

using MonPocGarage.ArmyContracts;
using MonPocGarage.ArmyContracts.Common;
using MonPocGarage.ArmyContracts.Common.Abilities;
using MonPocGarage.ArmyContracts.Common.Enums;
using MonPocGarage.Common.Extensions;
using MonPocGarage.Common.Logging;

namespace MonPocGarage.ArmyData.Builders
{
    internal static class BuildBuildingList
    {
        internal static List<Building> Build()
        {
            List<Building> buildings = new List<Building>();
            
            XmlDocument xDoc = new XmlDocument();
            try
            {
                foreach (string file in Directory.EnumerateFiles(Environment.CurrentDirectory + "/Data/Buildings"))
                {
                    xDoc.Load(file);
                    foreach (XmlNode xNode in xDoc.SelectNodes("Buildings/Building"))
                    {

                        if (xNode.SelectSingleNode("BuildingType").InnerText.ToEnumValue<BuildingType>() == BuildingType.Building)
                        {
                            buildings.Add(MapBuilding(xNode));   
                        }
                        else if (xNode.SelectSingleNode("BuildingType").InnerText.ToEnumValue<BuildingType>() == BuildingType.Installation)
                        {
                            buildings.Add(MapInstallation(xNode));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHandler.LogException("Unable to parse a Building", ex, MessageLevel.ERROR);
            }
            return buildings;
        }

        private static Building MapBuilding(XmlNode xNode)
        {
            List<IAbility> abilities = BuildAbilityList.GetAbilityList();
            Building mappedBuilding = new Building
                                          {
                                              BuildingName = xNode.SelectSingleNode("BuildingName").InnerText,
                                              Defense = Convert.ToInt32(xNode.SelectSingleNode("Defense").InnerText),
                                              Energy = Convert.ToInt32(xNode.SelectSingleNode("Energy").InnerText),
                                              HazardType = xNode.SelectSingleNode("HazardType").InnerText.ToEnumValue<HazardType>(),
                                              Abilities = new List<IAbility>()
                                          };
            foreach (XmlNode ability in xNode.SelectNodes("Abilities/Ability/AbilityID"))
            {
                IAbility mappedAbility = abilities.Where(a => a.AbilityID == ability.InnerText).FirstOrDefault();
                if (ability.Attributes["color"] != null)
                {
                    mappedAbility.ChangeColor(ability.Attributes["color"].Value.ToEnumValue<AbilityColor>());
                }
                if (ability.NextSibling != null && mappedAbility.AbilityType == AbilityType.Trigger)
                {
                    ((Trigger)mappedAbility).ChangeAttackType(ability.NextSibling.InnerText.ToEnumValue<AttackType>());
                }
                mappedBuilding.Abilities.Add((IAbility)mappedAbility.Clone());
            }
            return (Building)mappedBuilding.Clone();
        }

        private static Installation MapInstallation(XmlNode xNode)
        {
            List<IAbility> abilities = BuildAbilityList.GetAbilityList();
            Installation mappedInstallation = new Installation
                                                  {
                                                      BuildingName = xNode.SelectSingleNode("BuildingName").InnerText,
                                                      Defense = Convert.ToInt32(xNode.SelectSingleNode("Defense").InnerText),
                                                      Energy = Convert.ToInt32(xNode.SelectSingleNode("Energy").InnerText),
                                                      HazardType = xNode.SelectSingleNode("HazardType").InnerText.ToEnumValue<HazardType>(),
                                                      Stats = new StatBlock
                                                                  {
                                                                      Blast = Mappers.MapBlastStat(xNode.SelectSingleNode("Stats/Blast")),
                                                                      Brawl = Mappers.MapBrawlStat(xNode.SelectSingleNode("Stats/Brawl"))
                                                                  },
                                                      Abilities = new List<IAbility>()
                                                  };
            foreach (XmlNode ability in xNode.SelectNodes("Abilities/Ability/AbilityID"))
            {
                IAbility mappedAbility = abilities.Where(a => a.AbilityID == ability.InnerText).FirstOrDefault();
                if (ability.Attributes["color"] != null)
                {
                    mappedAbility.ChangeColor(ability.Attributes["color"].Value.ToEnumValue<AbilityColor>());
                }
                if (ability.NextSibling != null && mappedAbility.AbilityType == AbilityType.Trigger)
                {
                    ((Trigger)mappedAbility).ChangeAttackType(ability.NextSibling.InnerText.ToEnumValue<AttackType>());
                }
                mappedInstallation.Abilities.Add((IAbility)mappedAbility.Clone());
            }
            return (Installation)mappedInstallation.Clone();
        }
    }
}
